package com.ww.springboot.boot.controller;

import cn.hutool.json.JSONUtil;
import com.ww.springboot.boot.config.RedisUtils;
import com.ww.springboot.boot.dto.RedisTestDto;
import com.ww.springboot.boot.redisson.RedisLock;
import com.ww.springboot.boot.redisson.ratelimiter.RateLimiter;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @author ZH500
 */
@RestController
@RequestMapping("redis")
@AllArgsConstructor
public class RedisController {

    private final RedisUtils logisticsRedis;

    private final StringRedisTemplate redisTemplate;


    @RequestMapping("redLock")
    @RedisLock(value = "123", param = "#redisTestDto.test", leaseTime = -1)
    public String find(@RequestBody RedisTestDto redisTestDto) throws InterruptedException {
        System.out.println(redisTestDto);
        System.out.println("开始" + System.currentTimeMillis());
        Thread.sleep(100000);
        System.out.println("结束" + System.currentTimeMillis());
        return "";
    }

    @RequestMapping("rateLimiter")
    @RateLimiter(value = "rateLimiterTest", ttl = 10, timeUnit = TimeUnit.SECONDS)
    public String RateLimiterTest() throws InterruptedException {
        System.out.println("开始" + System.currentTimeMillis());
        Thread.sleep(2000);
        System.out.println("结束" + System.currentTimeMillis());
        return "";
    }


    @RequestMapping("test")
    public String test(String type) {
        switch (type) {
            case "0":
                logisticsRedis.del("redis:test:zero:string"
                        , "redis:test:zero:int"
                        , "redis:test:zero:long"
                        , "redis:test:zero:float"
                        , "redis:test:zero:list");
                //add
                logisticsRedis.set("redis:test:zero:string", "1aw+3?");
                logisticsRedis.set("redis:test:zero:int", 1);
                logisticsRedis.set("redis:test:zero:long", 1L);
                logisticsRedis.set("redis:test:zero:float", 1.1f);
                logisticsRedis.set("redis:test:zero:list", Arrays.asList(123, 345, 567));
                logisticsRedis.set("redis:test:zero:list:string", Arrays.asList("123", "345", "567"));

                System.out.println((String) logisticsRedis.get("redis:test:zero:string"));
                System.out.println((Integer) logisticsRedis.get("redis:test:zero:int"));
                System.out.println((Long) logisticsRedis.get("redis:test:zero:long"));
                System.out.println((Float) logisticsRedis.get("redis:test:zero:float"));
                List<Integer> list = logisticsRedis.get("redis:test:zero:list");
                System.out.println(list.toString());
                List<String> list1 = logisticsRedis.get("redis:test:zero:list:string");
                System.out.println(list1.toString());
                System.out.println("成功");
                break;
            case "1":
                //列表
                System.out.println(logisticsRedis.sAdd("redis:test:one:set", 1, 2, 3, 4, 5, 6, 7));
                System.out.println(logisticsRedis.sAdd("redis:test:one:set", 1, 2, 3, 4, 5, 6, 7));
                System.out.println(logisticsRedis.sAdd("redis:test:one:set", 8, 9, 0, 1, 2));
                Long size = logisticsRedis.getSetOps().size("redis:test:one:set");
                System.out.println(size);
                System.out.println(logisticsRedis.getSetOps().pop("redis:test:one:set", 2).toString());
                System.out.println(logisticsRedis.getSetOps().pop("redis:test:one:set", 3).toString());
                System.out.println(logisticsRedis.getSetOps().pop("redis:test:one:set", 4).toString());
                System.out.println(logisticsRedis.getSetOps().pop("redis:test:one:set", 5).toString());

                System.out.println("-------------------------list------------------------------");


                System.out.println(logisticsRedis.lPush("redis:test:one:list", 1, 2, 3));
                System.out.println(logisticsRedis.lPush("redis:test:one:list", 2, 3, 4));
                System.out.println(logisticsRedis.lPush("redis:test:one:list", 3, 4, 5));
                logisticsRedis.getListOps().set("redis:test:one:list", 0, 2);
                Long size2 = logisticsRedis.getListOps().size("redis:test:one:list");
                for (int i = 0; i < size2; i++) {
                    Object o = logisticsRedis.getListOps().leftPop("redis:test:one:list");
                    if (o instanceof Integer) {
                        System.out.println(o);
                    } else {
                        Object[] o1 = (Object[]) o;
                        System.out.println(Arrays.toString(o1));
                    }
                }

                break;
            case "2":
                //排行榜
                logisticsRedis.del("redis:test:two:set");
                for (int i = 0; i < 100; i++) {
                    double score = (Math.random() * 100);
                    System.out.println(i + ":" + score);
                    logisticsRedis.zAdd("redis:test:two:set", i, score);
                }
                Set set = logisticsRedis.zRevrange("redis:test:two:set", 1, 10);
                //从高到低
                System.out.println(set.toString());
                for (Object o : set) {
                    System.out.println(o + "-" +
                            logisticsRedis.zRevrank("redis:test:two:set", o) + "-" +
                            logisticsRedis.zScore("redis:test:two:set", o));

                }
                //从低到高
                System.out.println(logisticsRedis.zRange("redis:test:two:set", 1, 10).toString());
                break;
            case "3":
                //多set交互 操作
                break;
            case "4":
                //cluster
                for (int i = 0; i < 100; i++) {
                    redisTemplate.opsForValue().set(i + "", i + "");
                }
                break;
            case "5":
                break;
            case "6":
                break;
            case "7":
                break;
            case "8":
                break;
            case "9":
                break;
            default:
        }
        return "success";
    }

    @PostMapping("delete")
    public String delete(@RequestBody List<String> keys) {
        keys.forEach(key -> {
            System.out.println(key);
            logisticsRedis.del(key);
        });
        return "ok";
    }

    @GetMapping("keys")
    public String keys(String prefix) {
        long l = System.currentTimeMillis();
        Set<String> keys1 = logisticsRedis.keys(prefix + "*");
        long l1 = System.currentTimeMillis();
        System.out.println("耗时：" + (l1 - l));
        System.out.println(keys1.toString());
        return JSONUtil.toJsonStr(keys1);
    }


    @GetMapping("clearKeys")
    public String clearKeys(String prefix, Integer tenantId) {
        for (int i = 0; i < tenantId; i++) {
            String prefixKey = prefix.replace("tenantId","0000" + (i > 9 ? i : "0" + i));
            Set<String> keys = logisticsRedis.keys(prefixKey + "*");
            System.out.println(JSONUtil.toJsonStr(keys));
            keys.forEach(key -> {
                System.out.println(key);
                logisticsRedis.del(key);
            });
        }
        return "";
    }
}
